﻿const GRANT = 1073741824;
/* ========================= terms of permission =============================
1. name: the name of the target message receiver
2. bit:  A integer(32bit) is used to express the permissions of each user.
         Each bit from 0 to 30 expresses a specific permission.(Note there
         are only 31 types of permissions allowed.). Here the concept "bit"
         if just the index of the bits.
3. index: The permissions that users see here in the client are all existing
         permission names. All these available permission names form a array.
         The array here is the varaiable "permissions"([{name,bit},...]). The
         concept "index" refers to the index of each permission in this array.
4. the relation between the "bit" and "index":
    4.1. index=>bit
         if a user checked a permission name, that means he/she want to grant
         this permission to a person. Under the UI the specific bit of the
         target person's permission attribute should be set to 1. But here only
         the index of the permission can be known. So the transformation from
         index to bit is needed.
         To transform index to bit, at first query the permission entity in
         the array permissions using the index, then the "bit" information can
         be retrieved from the "bit" attribute of the entity.
*/

class PermConverter {
    constructor() {
        this.permissions = null;
    }

    init(perms) { this.permissions = perms }

    hasGrantPerm(perm) {
        return Number.isInteger(perm) && (perm & GRANT) > 0
    }

    perm2arr(perm) {
        // permissions failed to be initialized
        if (!this.permissions) return null;    

        /*  perm======= arr====================
         *  undefined   [{name,false},...]
         *  int         [{name,calculated},...]
         */
        var hasSomePerms = Number.isInteger(perm);
        return this.permissions.map(p => ({
            name: p.name,
            granted: hasSomePerms && (Math.pow(2, p.bit) & perm) > 0
        }))
    } 

    flipPerm(perm, idx) {
        if (!this.permissions) return 0;

        if (!perm) perm = 0;        // a user may has no any permission having attribute "perm" of null
        var mask = Math.pow(2, this.permissions[idx].bit);
        var newPerm = perm ^ mask;
        return newPerm === 0 ? undefined : newPerm;
    }
}

const singleConverter = new PermConverter();

export default singleConverter;